<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class RequestLog
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param \Closure $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $time1    = microtime(true);
        $response = $next($request);
        $time2    = microtime(true);

        // 记录所有请求信息
        $requestMessage = [
            'url'        => $request->url(),
            'method'     => $request->method(),
            'start_at'   => microtime_to_date_time_str($time1),
            'end_at'     => microtime_to_date_time_str($time2),
            'total_time' => sprintf('%.4f', ($time2 - $time1)) . 's',
            'ip'         => $request->ips(),
            'path'       => $request->path(),
            'headers'    => $request->header(),
            'query'      => $request->query(),
        ];

        if ($request->file()) {
            // 文件内容不做日志记录，使用<file>做标识
            $requestMessage['body'] = '<file>';
        } else {
            // 获取请求体Body信息
            $bodyContent = $request->all();
            // 从.env文件中获取参数内容的长度
            $parameterLength = \config('logging.request.value_max_length', 1000);

            if ($bodyContent && in_array($request->method(), ['POST', 'PATCH'])) {
                foreach ($request->all() as $key => $value) {
                    if (is_string($value) && Str::length($value) > $parameterLength) {
                        // 参数内容的长度过大的进行裁剪
                        $bodyContent[$key] = Str::limit($value, $parameterLength);
                    }
                }
            }
            $requestMessage['body'] = $bodyContent;
        }
        //记录请求日志(配置开启，且为有效请求（有请求路径）)
        // 保存至log文件
        $message = json_encode($requestMessage, JSON_UNESCAPED_SLASHES);
        $path    = base_path() . '/storage/logs/';
        if (!is_dir($path)) {
            mkdir($path, 0777, true);
        }
        $filename = $path . 'request' . date('_Y-m-d') . '.log';
        $content  = $message . "\r\n";
        file_put_contents($filename, $content, FILE_APPEND);

        return $response;
    }
}

/*
 * 将微秒数转换为时间字符串
 */
if (!function_exists('microtime_to_date_time_str')) {
    function microtime_to_date_time_str($microtime, $isFineness = false)
    {
        $timestamp    = floor($microtime);
        $milliseconds = round(($microtime - $timestamp) * 1000000);

        return date('Y-m-d H:i:s', $timestamp) . ($isFineness ? '.' . sprintf('%06d', $milliseconds) : '');
    }
}
